#include "cntr_photo.h"

ControllerPhoto::ControllerPhoto(InterfacePhoto * interface,cmd_photo * cmd)
                : Controller(interface,cmd),interface(interface),cmd(cmd){
    MIN_OPT = 0;
    MAX_OPT = 4;
    MAX_PHOTOSALBUM = 5;
    MAX_TOLERANCE = 3;
}

int ControllerPhoto::execute(){
    int opcao = 0;
    stringstream ss;
    exception exc;
    bool tf = true;
    while(tf){
        try{
            opcao = 0;
            opcao = interface->chooseOpt();
            if(opcao>MAX_OPT || opcao<MIN_OPT){
                ss << endl << "opcao invalida :" << opcao << endl;
                interface->inform(ss.str());
                break;
            }
        }catch (exception& e){

            ss << endl << "Erro (ControllerPhoto.execute.try.chooseOpt):" << endl;
            ss << e.what() << endl;

            interface->inform(ss.str());
            break;
        }

        ss << endl << "opcao digitada:" << opcao << endl;
        interface->inform(ss.str());
        ss.str(""); // limpar ss, caso contrario acumula mensagens
                    // usado apenas nesse ponto pq nos outros ocorre
                    // um break e o loop acaba

        switch(opcao){
            case 1:
                cadastrar();
                break;
            case 2:
                excluir();
                break;
            case 3:
                pesquisar();
                break;
            case 4:
                addPhotoAlbum();
                break;
            default:
                tf = false;
                break;
        }
    }

    return 0;
}

int ControllerPhoto::cadastrar(){
    int error = 0;
    interface->inform(interface->cad_info);

    string identificador,data;
    float velocidade,abertura;
    int iso;

    Identifier identifier;
    Date date;
    Speed speed;
    Openness openness;
    ISO Iso;

    while(true){
        try{
            interface->inform(interface->get_ident);
            identificador = interface->getString();
            identifier.set(identificador);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_date);
            data = interface->getString();
            date.set(data);
            //interface->inform(date.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_speed);
            velocidade = interface->getFloat();
            speed.set(velocidade);
            //interface->inform(speed.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_open);
            abertura = interface->getFloat();
            openness.set(abertura);
            //interface->inform(openness.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_iso);
            iso = interface->getInt();
            Iso.set(iso);
            //interface->inform(Iso.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    Photo * photo = new Photo(identifier,date,speed,openness,Iso);
    cmd->setPhoto(photo);
    cmd->setCmd(cmd_photo::CADASTRAR);

    try{
        Persistence::Instanciate()->Executar(cmd);
        interface->inform(interface->cad_ok);
    }catch(string str){
        throw(str);
    }

    return 0;
}

int ControllerPhoto::excluir(){
    int error = 0;
    interface->inform(interface->exc_info);

    string identificador;

    Identifier identifier;

    while(true){
        try{
            interface->inform(interface->get_ident);
            identificador = interface->getString();
            identifier.set(identificador);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    Photo * photo = new Photo();
    photo->setIdentifier(identifier);

    cmd->setPhoto(photo);

    cmd->setCmd(cmd_photo::CHECKEXCLUIR);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    if(!cmd->result.empty()){
        while(!cmd->result.empty()){
            cmd->result.pop_back();
        }
        throw(interface->err_excluir);
    }

    cmd->setCmd(cmd_photo::CHECKPHOTO);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    if(cmd->result.empty())
        throw(interface->err_not_found);

    cmd->setCmd(cmd_photo::EXCLUIR);
    try{
        Persistence::Instanciate()->Executar(cmd);
        interface->inform(interface->exc_ok);

    }catch(string str){
        throw(str);
    }

    return 0;
}

int ControllerPhoto::addPhotoAlbum(){
    int error = 0;
    interface->inform(interface->add_info);
    stringstream ss;

    string identificador;

    Identifier idPhoto,idAlbum;

    while(true){
        try{
            interface->inform(interface->add_album);
            identificador = interface->getString();
            idAlbum.set(identificador);
            //interface->inform(idAlbum.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    Album * album = new Album();
    album->setIdentifier(idAlbum);

    cmd->setAlbum(album);

    cmd->setCmd(cmd_photo::CHECKALBUM);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    if(cmd->result.empty()){
        throw(interface->err_addAlbum);
    }else{
        while(!cmd->result.empty()){
            cmd->result.pop_back();
        }
    }
    cmd->setCmd(cmd_photo::CHECKLIMITALBUM);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    if(cmd->callback_count==MAX_PHOTOSALBUM){
        while(!cmd->result.empty()){
            cmd->result.pop_back();
        }
        ss.str("");
        ss << MAX_PHOTOSALBUM << interface->err_add_limit;
        throw(ss.str());
    }

    while(true){
        try{
            interface->inform(interface->add_photo);
            identificador = interface->getString();
            idPhoto.set(identificador);
            //interface->inform(idPhoto.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }
    Photo * photo = new Photo();
    photo->setIdentifier(idPhoto);

    cmd->setPhoto(photo);
    cmd->setCmd(cmd_photo::CHECKPHOTO);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    if(cmd->result.empty()){
        throw(interface->err_addPhoto);
    }else{
        while(!cmd->result.empty()){
            cmd->result.pop_back();
        }
    }

    cmd->setCmd(cmd_photo::ADDPHOTOALBUM);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    interface->inform(interface->add_ok);

    return 0;
}


int ControllerPhoto::pesquisar(){
    int error = 0;
    interface->inform(interface->pes_info);
    stringstream ss;

    string identificador;

    Identifier identifier;

    while(true){
        try{
            interface->inform(interface->get_ident);
            identificador = interface->getString();
            identifier.set(identificador);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    Photo * photo = new Photo();
    photo->setIdentifier(identifier);

    cmd->setPhoto(photo);

    cmd->setCmd(cmd_photo::PESQUISAR);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    while(!cmd->result.empty()){
        string str = cmd->result.back();
        ss << str;
        cmd->result.pop_back();
    }
    interface->inform(ss.str());

    ss.str("");
    ss << endl << interface->pes_fim << cmd->callback_count << endl << endl;
    interface->inform(ss.str());

    return 0;
}

/********************************************************/

ControllerAlbum::ControllerAlbum(InterfaceAlbum * interface,cmd_album * cmd)
                : Controller(interface,cmd),interface(interface),cmd(cmd){
    MIN_OPT = 0;
    MAX_OPT = 4;
    MAX_USERALBUNS = 5;
    MAX_TOLERANCE = 3;
    MAX_PRICE = 100.0;
}

int ControllerAlbum::execute(){
    int opcao = 0;
    stringstream ss;
    exception exc;
    bool tf = true;
    while(tf){
        try{
            opcao = 0;
            opcao = interface->chooseOpt();
            if(opcao>MAX_OPT || opcao<MIN_OPT){
                ss << endl << "opcao invalida :" << opcao << endl;
                interface->inform(ss.str());
                break;
            }
        }catch (exception& e){

            ss << endl << "Erro (ControllerAlbum.execute.try.chooseOpt):" << endl;
            ss << e.what() << endl;

            interface->inform(ss.str());
            break;
        }

        ss << endl << "opcao digitada:" << opcao << endl;
        interface->inform(ss.str());
        ss.str(""); // limpar ss, caso contrario acumula mensagens
                    // usado apenas nesse ponto pq nos outros ocorre
                    // um break e o loop acaba

        switch(opcao){
            case 1:
                cadastrar();
                break;
            case 2:
                excluir();
                break;
            case 3:
                pesquisar();
                break;
            case 4:
                pesqPhotosAlbum();
                break;
            default:
                tf = false;
                break;
        }
    }

    return 0;
}

int ControllerAlbum::cadastrar(){
    cmd->setCmd(cmd_album::CHECKCADASTRAR);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    while(!cmd->result.empty()){
        cmd->result.pop_back();
    }

    if(cmd->callback_count==MAX_USERALBUNS){
        stringstream ss;
        ss << MAX_USERALBUNS << interface->err_cad_limit;
        throw(ss.str());
    }

    int error = 0;
    interface->inform(interface->cad_info);

    string identificador,descricao;
    int nivelacesso;
    float preco;

    Identifier identifier;
    Description description;
    AccessLevel accesslevel;
    Price price;

    while(true){
        try{
            interface->inform(interface->get_ident);
            identificador = interface->getString();
            identifier.set(identificador);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_desc);
            descricao = interface->getString();
            description.set(descricao);
            //interface->inform(description.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_accl);
            nivelacesso = interface->getInt();
            accesslevel.set(nivelacesso);
            //interface->inform(accesslevel.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    while(true){
        try{
            interface->inform(interface->get_price);
            preco = interface->getFloat();
            price.set(preco);
            //interface->inform(price.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    if(price.get()>MAX_PRICE){
        stringstream ss;
        ss << MAX_PRICE << interface->err_cad_price;
        throw(ss.str());
    }

    Album * album = new Album(identifier,description,accesslevel,price);

    cmd->setAlbum(album);
    cmd->setCmd(cmd_album::CADASTRAR);
    try{
        Persistence::Instanciate()->Executar(cmd);
        interface->inform(interface->cad_ok);
    }catch(string str){
        throw(str);
    }

    return 0;
}

int ControllerAlbum::excluir(){
    int error = 0;
    interface->inform(interface->exc_info);

    string identificador;

    Identifier identifier;

    while(true){
        try{
            interface->inform(interface->get_ident);
            identificador = interface->getString();
            identifier.set(identificador);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    Album * album = new Album();
    album->setIdentifier(identifier);

    cmd->setAlbum(album);

    cmd->setCmd(cmd_photo::CHECKEXCLUIR);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    if(!cmd->result.empty()){
        while(!cmd->result.empty()){
            cmd->result.pop_back();
        }
        throw(interface->err_excluir);
    }

    cmd->setCmd(cmd_album::EXCLUIR);
    try{
        Persistence::Instanciate()->Executar(cmd);
        interface->inform(interface->exc_ok);
    }catch(string str){
        throw(str);
    }


    return 0;
}

int ControllerAlbum::pesquisar(){
    int error = 0;
    interface->inform(interface->pes_info);
    stringstream ss;

    string identificador;

    Identifier identifier;

    while(true){
        try{
            interface->inform(interface->get_ident);
            identificador = interface->getString();
            identifier.set(identificador);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    Album * album = new Album();
    album->setIdentifier(identifier);

    cmd->setAlbum(album);
    cmd->setCmd(cmd_album::PESQUISAR);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    while(!cmd->result.empty()){
        string str = cmd->result.back();
        ss << str;
        cmd->result.pop_back();
    }
    interface->inform(ss.str());

    ss.str("");
    ss << endl << interface->pes_fim << cmd->callback_count << endl << endl;
    interface->inform(ss.str());

    return 0;
}

int ControllerAlbum::pesqPhotosAlbum(){
    int error = 0;
    interface->inform(interface->pes_info);
    stringstream ss;

    string identificador;

    Identifier identifier;

    while(true){
        try{
            interface->inform(interface->get_ident);
            identificador = interface->getString();
            identifier.set(identificador);
            //interface->inform(identifier.get());//teste if ok
            break;
        }catch(invalid_argument ia){
            interface->inform(ia.what());
            error++;
            if(error>MAX_TOLERANCE){
                throw(interface->err_tolerance);
            }
        }
    }

    Album * album = new Album();
    album->setIdentifier(identifier);

    cmd->setAlbum(album);
    cmd->setCmd(cmd_album::CHECKALBUM);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    if(cmd->result.empty()){
        throw(interface->err_album);
    }else{
        while(!cmd->result.empty()){
            cmd->result.pop_back();
        }
    }

    cmd->setCmd(cmd_album::PESQFOTOSALBUM);
    try{
        Persistence::Instanciate()->Executar(cmd);
    }catch(string str){
        throw(str);
    }

    while(!cmd->result.empty()){
        string str = cmd->result.back();
        ss << str;
        cmd->result.pop_back();
    }
    interface->inform(ss.str());

    ss.str("");
    ss << endl << interface->pes_fim << cmd->callback_count << endl << endl;
    interface->inform(ss.str());

    return 0;
}
